Refuse a pull request that does not target main - #463
Merged
Conversation
#452, #453 and #455 were each merged into a feature branch that had itself already been merged and deleted. GitHub reported MERGED for all three, and none of the work reached main. It was found later by checking file contents against origin/main, not by looking at badges. The badge cannot distinguish 'merged into main' from 'merged into a dead branch'. This check can, and it runs before the merge rather than after it. The branch name goes through env rather than into the shell body: base_ref is attacker-controllable from a fork, so interpolating it into run: would be a script injection. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The mechanical version of a discipline I have been applying by hand.
What it prevents
#452, #453 and #455 were each merged into a feature branch that had itself already been merged and deleted. GitHub reported MERGED for all three. None of the work reached
main. It was found later by checking file contents againstorigin/main—git cat-file -e origin/main:<path>— rather than by trusting the badge.The badge cannot distinguish "merged into main" from "merged into a dead branch". This check can, and it runs before the merge rather than after it.
Root cause was stacking three PRs deep and merging them in what looked like the natural order.
The check
One job, gated to pull requests, failing when
base_ref != mainwith a message explaining the failure mode rather than just the condition.base_refis passed throughenvrather than interpolated into the shell body — branch names are attacker-controllable from forks, so${{ github.base_ref }}insiderun:would be a script-injection hole.Verification
mainand rejectsepic/some-feature,fix/already-merged-branch, andmain; echo INJECTED(the last reaching the comparison as one literal string, not as shell).main, so the new check should pass on itself.Not included
Requiring an independent approval for compiler/runtime/validator changes is branch-protection configuration, not a workflow file. It governs whether this work can merge unreviewed, so it is a repository-owner decision rather than something to grant myself in a PR.
🤖 Generated with Claude Code